﻿/// <reference path="_references.js" />
/// <reference path="Markdown.Converter.js" />
/// <reference path="knockout-2.1.0.debug.js"/>

function ChatSocket(endpoint, protocol) {
    var ws;
    var events = [];
    var socketEndpoint = endpoint;
    var socketProtocol = protocol;
    var i = 0;

    var onMessage = function (messageEvent) {
        var data = $.parseJSON(messageEvent.data);
        for (i = 0; i < events.length; i++) {
            if (events[i].id === data.ActionId) {
                events[i].action(data);
            }
        }
    };

    this.onOpen = function () { };
    this.onClose = function () { };

    this.registerEvent = function (event) {
        events[events.length] = event;
    };

    this.open = function () {
        ws = new window.WebSocket(socketEndpoint, socketProtocol);
        ws.onopen = this.onOpen;
        ws.onmessage = onMessage;
    };

    this.close = function () {
        ws.onclose = this.onClose;
        ws.close();
    };

    this.send = function (data) {
        ws.send(data);
    };
}

function Notification() {
    var currentNotification = null;
    var unreadCount = 0;

    this.EnableNotifications = function () {
        var self = this;
        window.webkitNotifications.requestPermission(function () { self.IsEnabled = window.webkitNotifications.checkPermission() === 0; });
    };

    this.DisableNotifications = function () { this.IsEnabled = false; };
    this.IsEnabled = false;

    this.Notify = function (from, message) {
        if (document.hasFocus() || !this.IsEnabled) return;

        if (currentNotification === null) {
            currentNotification = window.webkitNotifications.createNotification('', 'New Messages!', from + ': ' + message);
            currentNotification.show();
            unreadCount = 1;
        } else {
            currentNotification.cancel();
            unreadCount++;
            currentNotification = window.webkitNotifications.createNotification('', 'New Messages', 'You have ' + unreadCount + ' unread messages');
            currentNotification.show();
        }
    };

    this.Reset = function () {
        if (currentNotification === null || currentNotification === undefined) return;
        currentNotification.cancel();
        currentNotification = null;
    };
}

//var socket = new ChatSocket('ws://chattr.cloudapp.net:8181', 'my-protocol');
var socket = new ChatSocket('ws://localhost:8181', 'my-protocol');

var notification = new Notification();

var currentUserId;
var converter = new Markdown.Converter();

function htmlEncode(value) {
    return value ? $('<div />').text(value).html() : '';

}

function htmlDecode(value) {
    return value ? $('<div />').html(value).text() : '';
}

function ChatMessage(serverResponse) {
    var self = this;
    self.userName = htmlEncode(serverResponse.User.Name);
    self.userId = htmlEncode(serverResponse.User.ConnectionId);
    self.message = ko.observable(converter.makeHtml(htmlEncode(serverResponse.Content)));
}

function MessageViewModel() {
    var self = this;
    self.messages = ko.observableArray();
    self.addMessage = function (serverResponse) {
        var lastMessage = self.messages.pop();
        if (lastMessage === undefined) {
            self.messages.push(new ChatMessage(serverResponse));
            return;
        }
        if (lastMessage.userId === serverResponse.User.ConnectionId) {
            lastMessage.message(lastMessage.message() + '<p>' + converter.makeHtml(htmlEncode(serverResponse.Content)) + '</p>');
            self.messages.push(lastMessage);
        } else {
            self.messages.push(lastMessage);
            self.messages.push(new ChatMessage(serverResponse));
        }
    };
}

function User(user) {
    var self = this;
    self.Id = user.ConnectionId;
    self.Name = user.Name;
}

function UsersViewModel() {
    var self = this;
    self.users = ko.observableArray();
    self.addUserGroup = function (users) {
        self.users.removeAll();
        for (var i = 0; i < users.length; i++) {
            self.users.push(new User(users[i]));
        }
    };

    self.addUser = function (user) {
        self.users.push(new User(user));
    };

    self.removeUSer = function (id) {
        var userToRemove = ko.utils.arrayFirst(self.users, function (user) {
            return id === user.Id;
        });

        self.users.remove(userToRemove);
    };
}

(function () {

    document.getElementById('chatItUp').addEventListener('click',
    function () {
        $.ajax("/chat/room", {
            success: function (data) {

                var request = { ActionId: 1, Content: '' };

                document.getElementById('chatContainer').innerHTML = data;
                document.getElementById('enableNotify').addEventListener('click', function () {
                    var caption;
                    if (!notification.IsEnabled) {
                        notification.EnableNotifications();
                        caption = 'disable notifications';
                    } else {
                        notification.DisableNotifications();
                        caption = 'enable notifications';
                    }
                    this.innerHTML = caption;
                });

                var input = document.getElementById('message');

                var status = document.getElementById('status');
                socket.onOpen = function () {
                    status.innerHTML = 'Connected \\o/';
                };

                socket.onClose = function () {
                    status.innerHTML = 'Closed :[';
                };

                var messagesViewModel = new MessageViewModel();
                ko.applyBindings(messagesViewModel, document.getElementById('chatBody'));

                var usersViewModel = new UsersViewModel();
                ko.applyBindings(usersViewModel, document.getElementById('usersContainer'));

                socket.registerEvent({
                    id: 1, action: function (response) {
                        messagesViewModel.addMessage(response);
                        var chatBody = document.getElementById('chatBody');
                        chatBody.scrollTop = chatBody.scrollHeight;
                        notification.Notify(response.User.Name, response.Content);
                    }
                });
                socket.registerEvent({ id: 5, action: function (response) { currentUserId = response.User.ConnectionId; } });
                socket.registerEvent({ id: 2, action: function (response) { usersViewModel.addUserGroup($.parseJSON(response.Content)); } });

                window.onfocus = function () {
                    notification.Reset();
                };

                input.addEventListener('keydown', function (event) {
                    if (event.keyCode === 13) {
                        if ($.trim(input.value).length == 0) return;
                        request.Content = input.value;
                        socket.send(JSON.stringify(request));
                        input.value = '';
                    }
                });

                socket.open();
            }
        });

    });
})();



